package de.micromata.icalour;

import org.apache.log4j.Logger;

import net.fortuna.ical4j.filter.Filter;
import net.fortuna.ical4j.filter.PeriodRule;
import net.fortuna.ical4j.model.Calendar;
import net.fortuna.ical4j.model.Component;
import net.fortuna.ical4j.model.ComponentList;
import net.fortuna.ical4j.model.DateTime;
import net.fortuna.ical4j.model.Dur;
import net.fortuna.ical4j.model.Period;
import net.fortuna.ical4j.model.Property;
import net.fortuna.ical4j.model.component.VEvent;

/**
 * This class controls the data, which was importet by the iCalendar file 
 */
public class DigitalFrame {
	
	private static Logger LOG = Logger.getRootLogger();
	private Calendar calendar;
	private ComponentList todaysList;
	private java.util.Calendar now;
	

	public DigitalFrame(Calendar calendar) {
		this.calendar = calendar;
	}
	
	/**
	 * Filters the events in the calendar object by time (only for current day)
	 * and by event format: VEvent
	 * 
	 * @param now
	 * 		current time, when receive a request by the client
	 */
	public void init(java.util.Calendar now) {
		this.now = now;
		
		// create a calendar object for the current day
		int remainingHoursToday = 24 - now.get(java.util.Calendar.HOUR_OF_DAY) + 1;
		
		// create a period until the end of the current day
		Period period = new Period(new DateTime(now.getTime()), new Dur(0, remainingHoursToday, 0, 0));
		Filter filter = new Filter(new PeriodRule(period));
		
		// filter only events, which start today
		todaysList = (ComponentList) filter.filter(calendar.getComponents(Component.VEVENT));
		todaysList = Utils.sortEvents(todaysList);
		LOG.debug(todaysList.size() + " events was found");
	}
	
	
	/**
	 * Converts java.util.Date to java.util.Calendar of the event start date
	 * @param event
	 * @return converted Date
	 */
	public java.util.Calendar getEventStartDate(VEvent event) {
		java.util.Calendar startDate = java.util.Calendar.getInstance();
		startDate.clear();
		startDate.setTime(event.getStartDate().getDate());
		return startDate; 
	}
	
	/**
	 * Converts java.util.Date to java.util.Calendar of the event end date
	 * @param event
	 * @return converted Date
	 */
	public java.util.Calendar getEventEndDate(VEvent event) {
		java.util.Calendar startEnd = java.util.Calendar.getInstance();
		startEnd.clear();
		startEnd.setTime(event.getEndDate().getDate());
		return startEnd; 
	}
	
	/**
	 * Returns true if the event takind place for more than one day, false otherwise
	 * @param event
	 */
	public boolean greaterThanOneDay(VEvent event) {
		java.util.Calendar eventStart = java.util.Calendar.getInstance();
		java.util.Calendar eventEnd = java.util.Calendar.getInstance();
		eventStart.clear();
		eventEnd.clear();
		eventStart.setTime(event.getStartDate().getDate());
		eventEnd.setTime(event.getEndDate().getDate());
		if (eventStart.get(java.util.Calendar.DAY_OF_MONTH) != eventEnd.get(java.util.Calendar.DAY_OF_MONTH)) {
			return true;
		} else {
			return false;
		}

	}
	
	/**
	 * Returns whether the event taking place now
	 * Check normal VEvents and frequently VEvents
	 * @param event
	 * @return true if event taking place now, false otherwise
	 */
	public boolean eventTakingPlaceNow(VEvent event) {
		boolean notFrequently = now.after(getEventStartDate(event))	&& now.before(getEventEndDate(event));
		boolean frequently = checkFrequentlyEvents(event);
		return (notFrequently || frequently);
	}
	
	/**
	 * Returns whether the event taking place now
	 * Check only frequently events
	 * 
	 * @param event
	 * @return true if event taking place now, false otherwise
	 */
	public boolean checkFrequentlyEvents(VEvent event) {
		/*
		 * For comparing the data, its neccessary to convert the events date format into a java.util.calendar object
		 */
		
		// check if the current event take place right now and draw a
		// rounded rectangle around the event
		boolean frequentlyEvents = false;
		// special check for frequently events, which have a RRULE property
		if (event.getProperty(Property.RRULE) != null) {
			// the frequently events have the wrong date, for comparing them
			// with the current time
			// create new calendar objects with the current date and the
			// time of the event
			java.util.Calendar finishEvent = (java.util.Calendar) now.clone();
			java.util.Calendar beginEvent = (java.util.Calendar) now.clone();
			finishEvent.set(java.util.Calendar.HOUR_OF_DAY, getEventEndDate(event).get(java.util.Calendar.HOUR_OF_DAY));
			finishEvent.set(java.util.Calendar.MINUTE, getEventEndDate(event).get(java.util.Calendar.MINUTE));
			beginEvent.set(java.util.Calendar.HOUR_OF_DAY, getEventStartDate(event).get(java.util.Calendar.HOUR_OF_DAY));
			beginEvent.set(java.util.Calendar.MINUTE, getEventStartDate(event).get(java.util.Calendar.MINUTE));

			// filter only events, which taking place right now
			if (now.after(beginEvent)) {
				Period period2 = new Period(new DateTime(now.getTime()), new DateTime(finishEvent.getTime()));
				Filter filter2 = new Filter(new PeriodRule(period2));
				ComponentList nowList = (ComponentList) filter2.filter(calendar.getComponents(Component.VEVENT));
				frequentlyEvents = !nowList.isEmpty();
			}
		}
		return frequentlyEvents;
	}
	
	/**
	 * @return true if the filtered event list is empty, false otherwise
	 */
	public boolean empty() {
		if (todaysList.size() == 0) {
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * @return the size of the filtered list
	 */
	public int getSize() {
		return todaysList.size();
	}
	
	/**
	 * @return the filtered list
	 */
	public ComponentList getAll() {
		return todaysList;
	}
	
	/**
	 * @param index
	 * @return return the index element of the list
	 */
	public VEvent getVEvent(int index) {
		return (VEvent) todaysList.get(index);
	}

}
